﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.ComponentModel;

namespace InductBase
{
    [TypeConverter(typeof(InductBase.Helpers.BasicTypesConverter))]
    public struct Vec2i
    {
        private int x;
        private int y;

        public int X { get { return x; } set { x = value; } }
        public int Y { get { return y; } set { y = value; } }

        public double Length
        {
            get
            {
                double oldLength = GetDistance(Vec2i.Null, this);
                return oldLength;
            }
            set
            {
                double oldLength = GetDistance(Vec2i.Null, this);
                x = (int)((x / oldLength) * value);
                y = (int)((y / oldLength) * value);
            }
        }

        public Vec2i(Vec2i other) { x = other.x; y = other.y; }
        public Vec2i(int x, int y) { this.x = x; this.y = y; }

        public static Vec2i operator +(Vec2i a, Vec2i b)
        {
            return new Vec2i(a.X + b.X, a.Y + b.Y);
        }

        public static Vec2i operator -(Vec2i a, Vec2i b)
        {
            return new Vec2i(a.X - b.X, a.Y - b.Y);
        }

        public static Vec2i operator *(Vec2i a, Vec2i b)
        {
            return new Vec2i(a.X * b.X, a.Y * b.Y);
        }

        public static Vec2i operator /(Vec2i a, Vec2i b)
        {
            return new Vec2i(a.X / b.X, a.Y / b.Y);
        }

        public static Vec2i operator *(Vec2i a, double b)
        {
            return new Vec2i((int)(a.X * b), (int)(a.Y * b));
        }

        public static Vec2i operator *(double b, Vec2i a)
        {
            return new Vec2i((int)(a.X * b), (int)(a.Y * b));
        }

        public static Vec2i operator /(Vec2i a, double b)
        {
            return new Vec2i((int)(a.X / b), (int)(a.Y / b));
        }

        public static bool operator ==(Vec2i a, Vec2i b)
        {
            return a.x == b.x && a.y == b.y;
        }

        public static bool operator !=(Vec2i a, Vec2i b)
        {
            return !(a.x == b.x && a.y == b.y);
        }

        public override bool Equals(object obj)
        {
            if (base.Equals(obj))
            {
                if (obj == (object)this) return true;
            }

            return false;
        }

        public double GetDistanceTo(Vec2i a)
        {
            Vec2i b = this;
            return Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
        }

        public Vec2i Copy()
        {
            return new Vec2i(this.X, this.Y);
        }
        public Vec2i Rotate(double angle)
        {
            angle = Math.PI * 2 * angle / 360.0;
            Vec2i res = new Vec2i();
            double cos = Math.Cos(angle);
            double sin = Math.Sin(angle);
            res.X = (int)(this.X * cos - this.Y * sin);
            res.Y = (int)(this.X * sin + this.Y * cos);
            return res;
        }

        public Vec2i Normed()
        {
            return this.Copy() / Length;
        }

        public static double GetDistance(Vec2i a, Vec2i b)
        {
            return Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
        }

        public static Vec2i Null = new Vec2i(0, 0);

        public static explicit operator Vec2i(Vec2 value)
        {
            return new Vec2i((int)value.X, (int)value.Y);
        }

        public static implicit operator Vec2(Vec2i value)
        {
            return new Vec2(value.X, value.Y);
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder("[", 10);
            sb.Append(x);
            sb.Append(";");
            sb.Append(y);
            sb.Append("]");
            return sb.ToString();
        }

        public static Vec2i Parse(string input)
        {
            input = input.Replace("[", "");
            input = input.Replace("]", "");
            string[] args = input.Split(';');
            return new Vec2i(int.Parse(args[0], CultureInfo.InvariantCulture), int.Parse(args[1], CultureInfo.InvariantCulture));
        }
    }
}
